package com.tiny.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;

import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.tiny.model.Menu;
import com.tiny.model.MenuPermission;
import com.tiny.model.Permission;
import com.tiny.model.RolePermission;

public class MenuController extends Controller {

	public void index() {
		render("/frame/menu.html");
	}
	
	public void save(){
		Menu menu = getModel(Menu.class);
		
		if (StrKit.notBlank(this.getPara("parent_id"))) {
			menu.set("parent_id", this.getPara("parent_id"));
		}
		else{
			menu.set("parent_id", 0);
		}
		menu.set("name", this.getPara("text"));
		menu.set("url", this.getPara("url"));
		menu.set("order", this.getPara("order"));

		setAttr("success", menu.save());
		renderJson();
	}
	
	public void edit(){
		Menu menu = getModel(Menu.class);
		
		if (StrKit.notBlank(this.getPara("parent_id"))) {
			menu.set("parent_id", this.getPara("parent_id"));
		}
		else{
			menu.set("parent_id", 0);
		}
		menu.set("name", this.getPara("text"));
		menu.set("url", this.getPara("url"));
		menu.set("order", this.getPara("order"));
		menu.set("id", this.getPara("id"));
		
		setAttr("success", menu.update());
		renderJson();
	}
	
	public void remove(){
		setAttr("success", Menu.dao.deleteById(this.getPara("id")));
		renderJson();
	}
	
	public void allMenu(){
		this.renderJson(selectShowMenus(null));
	}

	private List<Map<String, Object>> selectShowMenus(Integer rootId) {

		List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
		// 授权的菜单集合
		List<Menu> menuPermittedList = new ArrayList<Menu>();
		// 获取所有菜单
		List<Menu> menuList = Menu.dao.getAllMenu();
		// 获取所有权限
		List<Permission> permissionList = Permission.dao.getAllPermission();

		Subject subject = SecurityUtils.getSubject();

		if (subject.hasRole("admin")) {
			for (Menu menu : menuList) {
				menuPermittedList.add(menu);
			}
		}else {
			for (Menu menu : menuList) {
				List<Integer> permissionIdSet = MenuPermission.dao
						.selectPermissionIdSet(menu.getId());// 获取菜单所有的权限Id
				// 权限key集合
				List<String> perKeyList = new ArrayList<String>();
				if (permissionIdSet != null && !permissionIdSet.isEmpty()) {
					for (Integer perId : permissionIdSet) {
						Permission permission = Permission.dao.get(
								permissionList, perId.intValue());// 通过权限ID获取所有的权限
						perKeyList.add(permission.getKey());
					}
				}
				// 判断权限
				String[] permissions = perKeyList.toArray(new String[] {});
				boolean permittedAll = subject.isPermittedAll(permissions);
				if (permittedAll) {
					menuPermittedList.add(menu);
				}
			}
		}

		List<Integer> childrenIdList = null;
		if (rootId != null) {
			childrenIdList = getChildrenMenuIds(menuList, rootId);
			childrenIdList.add(rootId);
		}

		List<Menu> rootMenus = getRootMenus(menuPermittedList);
		for (Menu menu : rootMenus) {
			if (childrenIdList == null
					|| !childrenIdList.contains(menu.getId())) {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("id", menu.getId());
				map.put("text", menu.getName());
				map.put("order", menu.getOrder());
				// 菜单额外属性
				Map<String, Object> attrMap = new HashMap<String, Object>();
				attrMap.put("url", menu.getUrl());
				map.put("attributes", attrMap);
				map.put("url", menu.getUrl());
				List<Map<String, Object>> childrenMenus = getChildrenMenus(
						menuPermittedList, menu.getId(), childrenIdList);
				map.put("children", childrenMenus);
				maps.add(map);
			}
		}
		return maps;
	}

	/**
	 * 获取子级菜单
	 * 
	 * @param menus
	 * @param parentId
	 * @return
	 */
	private List<Map<String, Object>> getChildrenMenus(List<Menu> menus,
			Integer parentId, List<Integer> childrenIdList) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		for (Menu menu : menus) {
			if ((parentId == null && menu.getParentId() == null)
					|| (parentId != null && menu.getParentId() != null && menu
							.getParentId().intValue() == parentId.intValue())) {
				if (childrenIdList == null
						|| !childrenIdList.contains(menu.getId())) {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("id", menu.getId());
					map.put("text", menu.getName());
					// 菜单额外属性
					Map<String, Object> attrMap = new HashMap<String, Object>();
					attrMap.put("url", menu.getUrl());
					map.put("attributes", attrMap);
					map.put("url", menu.getUrl());
					map.put("order", menu.getOrder());
					List<Map<String, Object>> childrenMenus = getChildrenMenus(
							menus, menu.getId(), childrenIdList);
					map.put("children", childrenMenus);
					mapList.add(map);
				}
			}
		}
		return mapList;
	}

	/**
	 * 获取根菜单
	 * 
	 * @param menus
	 * @return
	 */
	private List<Menu> getRootMenus(List<Menu> menus) {
		List<Menu> rootMenus = new ArrayList<Menu>();
		for (Menu menu : menus) {
			if (menu.getParentId() == null) {
				rootMenus.add(menu);
				continue;
			}
			Menu parentMenu = Menu.dao
					.get(menus, menu.getParentId().intValue());
			if (parentMenu == null) {
				rootMenus.add(menu);
			}
		}
		return rootMenus;
	}

	/**
	 * 获取所有子级菜单id集合
	 * 
	 * @param menuList
	 * @param parentId
	 * @return
	 */
	private List<Integer> getChildrenMenuIds(List<Menu> menuList,
			Integer parentId) {
		List<Integer> list = new ArrayList<Integer>();
		for (Menu menu : menuList) {
			if ((parentId == null && menu.getParentId() == null)
					|| (parentId != null && menu.getParentId() != null && parentId
							.intValue() == menu.getParentId().intValue())) {
				list.add(menu.getId().intValue());
				list.addAll(getChildrenMenuIds(menuList, menu.getId()
						.intValue()));
			}
		}
		return list;
	}

	public void managePermission(){
		Db.update(" delete from MenuPermission where menu_id=? ",this.getPara("id"));
		Integer[] pids=this.getParaValuesToInt("permission_id");
		for(Integer id:pids){
			MenuPermission rp=new MenuPermission();
				rp.set("menu_id", this.getPara("id"));
				rp.set("permission_id", id);
				setAttr("success", rp.save());
		}
		renderJson();
	}
	
	public void getPermissions(){
		renderJson(Db.find(" select permission_id as id from MenuPermission where menu_id=? ",this.getPara("id")));
	}
}